package conf

import (
	"errors"
	"time"

	"github.com/spf13/viper"
)

type BackendInfo struct {
	Addr     string
	Path     string
	History  time.Duration
	Interval time.Duration
}

type RpcmonConf struct {
	EtcdAddr   string
	BackendMap map[string]*BackendInfo
	AllHistory time.Duration
	MaxHistory time.Duration
}

type OWLConf struct {
	Menus      string
	BackendMap map[string]*BackendInfo
	AllHistory time.Duration
	MaxHistory time.Duration
}

type GatewayConf struct {
	Rpcmon   *RpcmonConf
	OWL      *OWLConf
	ConfPath string
	LogFile  string
	LogLevel string
	Addr     string
	Cert     string
	Key      string
	Index    string
	TokenTTL time.Duration
}

func New(file string) (*GatewayConf, error) {
	rpcmon := &RpcmonConf{
		BackendMap: make(map[string]*BackendInfo, 0),
	}
	owl := &OWLConf{
		BackendMap: make(map[string]*BackendInfo, 0),
	}

	cnf := &GatewayConf{
		ConfPath: file,
		Rpcmon:   rpcmon,
		OWL:      owl,
	}

	v := viper.New()
	v.SetConfigFile(file)

	err := v.ReadInConfig()
	if err != nil {
		return nil, err
	}

	rMap := v.GetStringMap("rpcmon.data")
	for k, v := range rMap {
		dst := v.(map[string]interface{})
		b := &BackendInfo{}

		history, ok := dst["history"]
		if !ok {
			b.History = time.Duration(0)
		} else {
			b.History = time.Duration(history.(int64)) * time.Second
		}

		interval, ok := dst["interval"]
		if !ok {
			b.Interval = time.Duration(1) * time.Second
		} else {
			b.Interval = time.Duration(interval.(int64)) * time.Second
		}

		addr, ok := dst["addr"]
		if !ok {
			return nil, errors.New("rpcmon data addr miss")
		} else {
			b.Addr = addr.(string)
		}

		path, ok := dst["path"]
		if !ok {
			b.Path = "/"
		} else {
			b.Path = path.(string)
		}

		rpcmon.BackendMap[k] = b
	}

	maxHistory := v.GetInt64("rpcmon.max_history")
	if maxHistory <= 0 {
		maxHistory = 3600
	}
	rpcmon.MaxHistory = time.Duration(maxHistory) * time.Second

	allHistory := v.GetInt64("rpcmon.all_history")
	if allHistory <= 0 {
		allHistory = 30
	}
	rpcmon.AllHistory = time.Duration(allHistory) * time.Second

	etcd := v.GetString("rpcmon.etcd")
	if etcd == "" {
		return nil, errors.New("rpcmon.etcd must exists")
	}
	rpcmon.EtcdAddr = etcd

	rMap = v.GetStringMap("owl.data")
	for k, v := range rMap {
		dst := v.(map[string]interface{})
		b := &BackendInfo{}

		history, ok := dst["history"]
		if !ok {
			b.History = time.Duration(0)
		} else {
			b.History = time.Duration(history.(int64)) * time.Second
		}

		interval, ok := dst["interval"]
		if !ok {
			b.Interval = time.Duration(1) * time.Second
		} else {
			b.Interval = time.Duration(interval.(int64)) * time.Second
		}

		addr, ok := dst["addr"]
		if !ok {
			return nil, errors.New("rpcmon data addr miss")
		} else {
			b.Addr = addr.(string)
		}

		path, ok := dst["path"]
		if !ok {
			b.Path = "/"
		} else {
			b.Path = path.(string)
		}

		owl.BackendMap[k] = b
	}

	maxHistory = v.GetInt64("owl.max_history")
	if maxHistory <= 0 {
		maxHistory = 3600
	}
	owl.MaxHistory = time.Duration(maxHistory) * time.Second

	allHistory = v.GetInt64("owl.all_history")
	if allHistory <= 0 {
		allHistory = 30
	}
	owl.AllHistory = time.Duration(allHistory) * time.Second

	menus := v.GetString("owl.menus")
	if menus == "" {
		return nil, errors.New("owl.menus must exists")
	}
	owl.Menus = menus

	addr := v.GetString("gateway.addr")
	if addr == "" {
		addr = "8080"
	}
	cnf.Addr = addr

	index := v.GetString("gateway.index")
	if index == "" {
		index = "./html/index.html"
	}
	cnf.Index = index

	ttl := v.GetInt("gateway.token_ttl")
	if ttl <= 0 {
		ttl = 60
	}
	cnf.TokenTTL = time.Duration(ttl) * time.Second

	logfile := v.GetString("log.file")
	if logfile == "" {
		logfile = "gateway.log"
	}
	cnf.LogFile = logfile

	loglevel := v.GetString("log.level")
	if loglevel == "" {
		loglevel = "info"
	}
	cnf.LogLevel = loglevel

	cnf.Cert = v.GetString("gateway.cert")
	cnf.Key = v.GetString("gateway.key")

	return cnf, nil
}
